package com.mall.user.services;
/*
 * @ClassName : IRegisterServiceImpl
 * @Description :
 * @Author : Jason
 * @Date : 2021/7/21 09:12:38
 * @Version : V1.0
 */

import com.alibaba.fastjson.JSON;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.IRegisterService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.converter.UserConverterMapper;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.entitys.UserVerify;
import com.mall.user.dal.persistence.MemberMapper;
import com.mall.user.dal.persistence.UserVerifyMapper;
import com.mall.user.dto.*;
import com.mall.user.utils.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

@Service
@Slf4j
@Transactional
public class IRegisterServiceImpl implements IRegisterService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private UserVerifyMapper userVerifyMapper;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    UserConverterMapper userConverterMapper;

    @Override
    public UserRegisterResponse register(UserRegisterRequest userRegisterRequest) {

        UserRegisterResponse response = new UserRegisterResponse();
        //判空验证
        userRegisterRequest.requestCheck();

        //判断用户名是否重复
        volidUserNameRequest(userRegisterRequest);

        //向表中插入数据
        Member member = new Member();
        member.setUsername(userRegisterRequest.getUserName());
        member.setEmail(userRegisterRequest.getEmail());

        //password需要加密处理
        String userPwd = DigestUtils.md5DigestAsHex(userRegisterRequest.getUserPwd().getBytes());
        //向用户表中插入数据
        member.setPassword(userPwd);
        member.setCreated(new Date());
        member.setUpdated(new Date());
        member.setState(1);
        member.setIsVerified("N");
        int effectRows = memberMapper.insert(member);
        if(effectRows!=1){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚事务
            response.setCode(SysRetCodeConstants.USER_REGISTER_FAILED.getCode());
            response.setMsg(SysRetCodeConstants.USER_REGISTER_FAILED.getMessage());
            return  response;
        }

        //向验证表中插入数据
        UserVerify userVerify = new UserVerify();
        userVerify.setUsername(userRegisterRequest.getUserName());
        String key = member.getUsername()+member.getPassword()+ UUID.randomUUID().toString();
        String uuid = DigestUtils.md5DigestAsHex(key.getBytes());
        userVerify.setUuid(uuid);
        userVerify.setRegisterDate(new Date());
        userVerify.setIsVerify("N");
        userVerify.setIsExpire("N");
        int effectRowsVerify = userVerifyMapper.insert(userVerify);
        if(effectRowsVerify!=1){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚事务
            response.setCode(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getCode());
            response.setMsg(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED .getMessage());
            return response;
        }

        //发送邮件
        SendEmail sendEmail = new SendEmail(uuid,userRegisterRequest);
        sendEmail.start();

        //打印日志，并返回成功的
        log.info("用户注册成功，注册参数为：{}", JSON.toJSONString(userRegisterRequest));
        response.setCode(SysRetCodeConstants.SUCCESS.getCode());
        response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return response;
    }

    /**
     * 登录验证接口
     * @param request 请求参数
     * @return UserLoginResponse
     */
    @Override
    public UserLoginResponse login(UserLoginRequest request) {
        UserLoginResponse response = new UserLoginResponse();
        //参数检验
        request.requestCheck();

        //根据账户查询表中的记录
        Example example = new Example(Member.class);
        example.createCriteria().andEqualTo("username",request.getUserName());
        List<Member> members = memberMapper.selectByExample(example);
        //如果查询不到则返回错误代码
        if(CollectionUtils.isEmpty(members)){
            response.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            response.setMsg(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
            return response;
        }
        //如果不为空，则将传入的密码加密
        Member member = members.get(0);
        String password = request.getPassword();
        String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());

        //对比传入的密码和数据库中的密码，不相等则返回错误代码
        if(!md5Password.equals(member.getPassword())){
            response.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            response.setMsg(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
            return response;
        }

        //如果该用户未验证则登录不成功
        String isVerified = member.getIsVerified();
        if("N".equals(isVerified))
        {
            response.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR.getCode());
            response.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR.getMessage());
            return response;
        }

        //将id，file,账户名封装到token中
        Map map = new HashMap<String,Object>();
        map.put("uid",member.getId());
        map.put("file",member.getFile());
        map.put("username",member.getUsername());

        String token = JwtTokenUtils.builder().msg(JSON.toJSONString(map)).build().creatJwtToken();

        response = userConverterMapper.converter(member);
        response.setToken(token);
        response.setCode(SysRetCodeConstants.SUCCESS.getCode());
        response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return response;
    }

    /**
     * 邮件验证接口
     * @param uid 密码
     * @param username 用户名
     * @return UserVerifyResponse
     */
    @Override
    public UserVerifyResponse verify(String uid, String username) {
        //根据uid和username更新用户验证表验证状态
        UserVerifyResponse userVerifyResponse = new UserVerifyResponse();
        UserVerify userVerify = new UserVerify();
        userVerify.setIsVerify("Y");
        Example example = new Example(UserVerify.class);
        example.createCriteria().andEqualTo("username",username).andEqualTo("uuid",uid);
        int affectRow = userVerifyMapper.updateByExampleSelective(userVerify,example);

        if(affectRow!=1){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            userVerifyResponse.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR .getCode());
            userVerifyResponse.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR  .getMessage());
            return userVerifyResponse;
        }

        //更新用户表验证状态
        Member member = new Member();
        member.setIsVerified("Y");
        Example example1 = new Example(Member.class);
        example1.createCriteria().andEqualTo("username",username);
        int affectRow2 = memberMapper.updateByExampleSelective(member,example1);

        if(affectRow2!=1){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            userVerifyResponse.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR .getCode());
            userVerifyResponse.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR  .getMessage());
            return userVerifyResponse;
        }

        userVerifyResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        userVerifyResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return  userVerifyResponse;
    }

    /**
     * 发送电子邮件的方法
     * @param uuid 用户加密后的密码
     * @param userRegisterRequest 注册请求封装参数
     */
    private void sendEmail(String uuid, UserRegisterRequest userRegisterRequest) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("Okane_mall_plus用户激活邮件");
        message.setFrom("18713501029@163.com");
        message.setTo(userRegisterRequest.getEmail());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://localhost:8080/user/verify?uid=").append(uuid).append("&username=").append(userRegisterRequest.getUserName());
        message.setText(stringBuilder.toString());
        mailSender.send(message);
    }

    /**
     * 验证账户是否存在
     * @param userRegisterRequest  注册请求参数
     */
    private void volidUserNameRequest(UserRegisterRequest userRegisterRequest) {
        Example example = new Example(Member.class);
        example.createCriteria().andEqualTo("username",userRegisterRequest.getUserName());
        List<Member> members = memberMapper.selectByExample(example);
        if(!CollectionUtils.isEmpty(members)){
            throw new ValidateException(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getCode(),SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getMessage());
        }
    }

    /**
     * 多线程内部类用于 发送电子邮件，防止token失效
     */
    class SendEmail extends Thread{
        String uuid;
        UserRegisterRequest userRegisterRequest;

        SendEmail(String uuid,UserRegisterRequest userRegisterRequest){
            this.uuid= uuid;
            this.userRegisterRequest= userRegisterRequest;
        }
        @Override
        public void run() {
            sendEmail(uuid,userRegisterRequest);
        }
    }
}


